<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
// 0. es6继承
class Parent {
    constructor () {

    }
    name = 'parent'
    play = [1, 1, 1]
}

class Child extends Parent {
    constructor () {
        super()
    }
    type = 'child'
}

var s = new Child()
console.log('0. class extends:', s)

    
// 1. 原型链继承 -- 改变Child1.prototype属性会影响全部实例
function Parent1 () {
    this.name = 'parent1'
    this.play = [1, 2, 3]
}

Parent1.prototype.say = function () {
    console.log('name:', this.name)
}

function Child1 () {
    this.type = 'child1'
}
// * 原型链继承
Child1.prototype = new Parent1()

var s1 = new Child1()
var s11 = new Child1()
s11.play.push(1)
console.log('1. 原型链继承：', s1)


// 2. 构造函数继承
function Parent2 () {
    this.name = 'parent2'
    this.play = [1, 2, 3]
}
Parent2.prototype.say = function () {
    console.log('name:', this.name)
}
function Child2 () {
    // * 构造函数继承
    Parent2.call(this)
    this.type = 'child2'
}
var s2 = new Child2()

console.log('2. 构造函数继承：', s2)
// s2.say() 没有继承原型方法


// 3. 组合继承 -- 1.Parent3执行两次，增加额外开销 2. 属性重复， parent属性会分别出现在s3实例和s3.prototype上
function Parent3 () {
    this.name = 'parent3'
    this.play = [1, 2, 3]
}
Parent3.say = function () {
    console.log('name:', this.name)
}

function Child3 () {
    // * 组合继承1 - 函数继承
    Parent3.call(this)
    this.type = 'child3'
}
// * 组合继承2 - 原型链继承
Child3.prototype = new Parent3()
Child3.prototype.constructor = Child3

var s3 = new Child3()
console.log('3. 组合继承：', s3)



// 4. 原型式继承 -- 拷贝
function Parent4 () {
    this.name = 'patent4'
    this.type = [1, 2, 3]
}
Parent4.prototype.say = function () {
    console.log('name:', this.name)
}
var p4 = new Parent4
var s4 = Object.create(p4)
var s41 = Object.create(p4)
// 等同于
// var s41 = {}
// s41.__proto__ = new Parent4
console.log('4. 原型式继承：', s4)
console.log('4. 原型式继承：', s41)
s4.type.push(1)



// 5. 寄生式继承
function Parent5 () {
    this.name = 'parent5'
    this.type = [1, 2, 3]
}
Parent5.prototype.say = function () {
    console.log('name:', this.name)
}
var p5 = new Parent5()

function clone (original) {
    let clone = Object.create(original)
    clone.hello = function () {
        console.log('type:', this.type)
    }
    return clone
}
let s5 = clone(p5)
console.log('5. 寄生式继承:', s5)


// 6. 寄生组合式继承
function Parent6 () {
    this.name = 'parent6'
    this.type = [1, 2, 3]
}
Parent6.prototype.say = function () {
    console.log('name:', this.name)
}
function Child6 () {
    Parent6.call(this)
    this.play = 'child6.play'
}

function clone2 (parent, child) {
    // console.log('parent:', parent)
    child.prototype = Object.create(parent.prototype)
    child.prototype.constructor = child
}

clone2(Parent6, Child6)

Child6.prototype.toPlay = function () {
    console.log('to play:', this.play)
}

var s6 = new Child6()
console.log('6. 寄生组合式继承:', s6)

</script>
</body>
</html>